#!/usr/bin/python
# coding=utf8
###############################################################################
#                                                                             #
#    Copyright 2007 Danil Dotsenko                                            #
#                                                                             #
#    This program is free software; you can redistribute it and/or modify     #
#    it under the terms of the GNU General Public License as published by     #
#    the Free Software Foundation, version 2 of the License.                  #
#                                                                             #
#    This program is distributed in the hope that it will be useful,          #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
#    GNU General Public License for more details.                             #
#                                                                             #
#    You should have received a copy of the GNU General Public License        #
#    along with this program; if not, write to the Free Software              #
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA #
#                                                                             #
###############################################################################                                   #
# Contacts: Danil Dotsenko, dd@accentsolution.com

import re
from commands import getoutput
import os

class helper:
	iconspath = []
	iconspathcache = {}
	versions = {}
	variables = {}
	icons = {}
	iconscache = {'16x16':{},'22x22':{},'32x32':{},'48x48':{},'64x64':{},'128x128':{},'scalable':{}}
	errors = []
	
	mimeicondb = {
		'audio':'sound',
		'image':'image',
		'video':'video',
		'application':{},
		'text':{},
		'':'unknown',
		None:'unknown',
		}
	mimeicondb['application']={
		'msword':'document',
		'rtf':'document',
		'pdf':'pdf',
		'rar':'package',
		'vnd.ms-excel':'spreadsheet',
		'vnd.oasis.opendocument.chart':'drawing',
		'vnd.oasis.opendocument.database':'package',
		'vnd.oasis.opendocument.formula':'spreadsheet',
		'vnd.oasis.opendocument.graphics':'drawing',
		'vnd.oasis.opendocument.graphics-template':'drawing',
		'vnd.oasis.opendocument.image':'image',
		'vnd.oasis.opendocument.presentation':'presentation',
		'vnd.oasis.opendocument.presentation-template':'presentation',
		'vnd.oasis.opendocument.spreadsheet':'spreadsheet',
		'vnd.oasis.opendocument.spreadsheet-template':'spreadsheet',
		'vnd.oasis.opendocument.text':'document',
		'vnd.oasis.opendocument.text-master':'document',
		'vnd.oasis.opendocument.text-template':'document',
		'vnd.oasis.opendocument.text-web':'html',
		'wordperfect':'document',
		'x-7z-compressed':'package',
		'x-bittorrent':'torrent',
		'x-font':'font',
		'x-iso9660-image':'cdrom_mount',
		'x-javascript':'binary',
		'x-kpresenter':'presentation',
		'x-kspread':'spreadsheet',
		'x-kword':'document',
		'x-latex':'document',
		'x-lha':'package',
		'x-lyx':'document',
		'x-lzh':'package',
		'x-python-code':'binary',
		'x-quicktimeplayer':'video',
		'x-redhat-package-manager':'package',
		'x-shockwave-flash':'video',
		'x-tar':'package',
		'x-xcf':'package',
		'xhtml+xml':'html',
		'xml':'html',
		'zip':'package',
		}
	mimeicondb['text']={
		'calendar':'spreadsheet',
		'css':'html',
		'csv':'spreadsheet',
		'html':'html',
		'plain':'txt',
		'richtext':'document',
		'tab-separated-values':'spreadsheet',
		'x-c++hdr':'binary',
		'x-c++src':'binary',
		'x-csh':'binary',
		'x-csrc':'binary',
		'x-diff':'binary',
		'x-haskell':'binary',
		'x-java':'binary',
		'x-pascal':'binary',
		'x-pascal':'binary',
		'x-perl':'binary',
		'x-python':'binary',
		'x-sh':'binary',
		'x-vcalendar':'binary',
		'x-vcard':'binary',
		}

	def iconForMime(self, fileMimeType):
		'''
		Provides a path-less icon TITLE ("unknown" for unknown.png) for a mime type/group
		
		I came up with this fast and full of holes algorythm because
		pyKDE would give me segfaults when I use it. It doesn't matter why the segfaults were there,
		I don't want the users to have to figure this out.

		This is very basic and is based on my own mime <> icon matching DB
		'''
		# the plan:
		# 1. Brake the mime in family and detail
		# 2. Pull result for family and see if it is a tree of furhter results.
		# 3. if a tree, look further until we either fall off of range of choices or find exact match.
		if fileMimeType:
			f, c = fileMimeType.split('/',1)
			icon = self.mimeicondb[f]
			if type(icon)==type({}):
				try:
					icon = icon[c]
				except:
					icon = 'unknown'
		else:
			icon = self.mimeicondb['']
		return icon

	def configReader(self, group, key, keytype=None, path=None, default=None):
		'''
		A wrapper for kreadconfig
		--file <file>             Использовать <file> вместо глобальной конфигурации
		--group <group>           Искать в заданной группе. [KDE]
		--key <key>               Искать данный параметр.
		--default <default>       Значение по умолчанию.
		--type <type>
		'''
		cmd = 'kreadconfig --group "%s" --key "%s"' % (group, key)
		if keytype:
			cmd = cmd + ' --type "%s"' % keytype
		if path:
			cmd = cmd + ' --file "%s"' % path
		if default:
			cmd = cmd + ' --default "%s"' % default
		return getoutput(cmd)

	############################
	# this is a helper for getIconPath
	def __detecticonpaths__(self):
		# looking for the config files, listing our and system's preferred icon theme.
		icondirs = getoutput('kde-config --path icon').split(':')
		icondirs.reverse()
		themes = {} # dict type with theme name as a key and theme path as key's arg
		if icondirs:
			folders = set(['index.theme', '64x64', '48x48', '32x32', '22x22', '128x128', '16x16'])
			for path in icondirs:
				# now path is a general path to folder with icon sets, like /usr/share/icons/
				if os.path.isdir(path):
					b = os.listdir(path) # now, b is a list of individual icon set folders (i hope) in that main folder.
					for i in b:
						# now, i is an individual icon set folder.
						try:
							c = list(folders.intersection(set(os.listdir(path+i))))
						except:
							c = []
						if ('index.theme' in c) and (c.__len__()>2):
							themes[i] = path
		
		# extracting the name of the preferred theme out of the cfg files.
		# this functions also sets the order of where we look for icons.
		themenames = []
		cfgdirs = getoutput('kde-config --path config').split(':')
		for path in cfgdirs:
			if os.path.isfile(path+'kdeglobals'):
				a = self.configReader('Icons', 'Theme', path=path+'kdeglobals')
				if a:
					themenames.append(a)
		# this is a backup. If neither user nor the system has a name of the theme in any rc, we hardcode it.
		# see http://developer.kde.org/~larrosa/iconthemes.html for sta
		for i in ['crystalsvg','hicolor']: 
			if not themenames.count(i):
				themenames.append(i)

		def __parsethemefile__(themepath, db):
			# A. The normal approach to reading the icon themes, looking at index.theme
			# need 2 things: 1) the folders the theme contains and
			# 2) on which theme this theme depends.
			depends = self.configReader('Icon Theme', 'Inherits', path=themepath+'/index.theme')
			dirs = self.configReader('Icon Theme', 'Directories', path=themepath+'/index.theme').split(',')
			if dirs:
				for i in dirs:
					# [...,'16x16/mimetypes', '22x22/actions', '22x22/apps',...]
					if i:
						size, trash = i.split('/',1)
						if size in ['64x64', '48x48', '32x32', '22x22', '128x128', '16x16']:
							db[size].append(themepath+'/'+i+'/') # which makes it a full name
			return depends
		
		# Now we are going to walk though the chain of icon themes and resolve their dependents.
		# this means that in addition to the prescribed themes we got out of kdeglobals above,
		# we look at those theme's depends and add them to the list.
		depends = None
		investigated = []
		while depends or themenames:
			if not depends:
				theme = themenames.pop(0)
			else:
				theme = depends
			if theme in investigated:
				depends = None
			else:
				investigated.append(theme)
				if os.path.isfile(themes[theme]+theme+'/index.theme'):
					depends = __parsethemefile__(themes[theme]+theme, self.icons)

	def iconPath(self, name, size):
		'''
		Takes an icon title, like "txt" for txt.png, or "unknown" for unknown.png
		If not found, returns ''. Note this behavior is different from KDE's which returns path to unknown.png
		name = "kate" for "/path/to/kate.png"
		size = size of the icon as in "16", "22", "32" etc.
		'''
		if not self.icons.has_key('16x16'):
			self.icons.update({'16x16':[],'22x22':[],'32x32':[],'48x48':[],'64x64':[],'128x128':[],'scalable':[]})
			self.__detecticonpaths__()
		size = str(size)+'x'+str(size)
		if name[-4:] != '.png':
			name = name + '.png'
		try:
			r = self.iconscache[size][name]
		except:
			r = ''
		i = 0
		# If r='', we are looking at the filesystem in search of the file.
		# types of actions subfolders:
		# 'actions/','apps/','devices/','filesystems/','mimetypes/'
		# 128x128  16x16  22x22  32x32  48x48  64x64
		while (not r) and (i < self.icons[size].__len__()): # while the file in to found and the end of icons-path-list is not reached.
			if os.path.isfile(self.icons[size][i] + name):
				r = self.icons[size][i] + name
				self.iconscache[size][name] = r
			i += 1
		return r
	
	def version(self, prog):
		prog = prog.upper()
		try:
			return self.versions[prog]
		except:
			kde = '(?<=KDE:) +[\d\.]*'
			sk = '(?<=SuperKaramba:) +[\d\.]*'
			ret = getoutput('superkaramba --version')
			try:
				kdever = re.search(kde, ret).group().strip().split('.')
				for i in range(kdever.__len__()):
					try:
						kdever[i] = int(kdever[i])
					except:
						pass
			except:
				kdever = [0,0] # major, minor numbers
			try:
				skver = re.search(sk, ret).group().strip().split('.')
				for i in range(skver.__len__()):
					try:
						skver[i] = int(skver[i])
					except:
						pass
			except:
				skver = [0,0] # major, minor numbers
			self.versions['SK'] = skver
			self.versions['SUPERKARAMBA'] = skver
			self.versions['KDE'] = kdever
			return self.versions[prog]
	
	def screeninfo(self):
		try:
			return self.variables['screeninfo']
		except:
			ret = getoutput('xdpyinfo')
			dimobj = re.compile('(?<=dimensions:)[ ]+\d+x\d+')
			dpiobj = re.compile('(?<=resolution:)[ ]+\d+x\d+')
			try:
				x, y = dimobj.search(ret).group().strip().split('x')
				x = int(x)
				y = int(y)
			except:
				x,y = 0,0
			try:
				d1, d2 = dpiobj.search(ret).group().strip().split('x')
				dpi = (int(d1)+int(d2))/2
			except:
				dpi = 0
			self.variables['screeninfo'] = (x,y,dpi)
			return (x,y,dpi)

if __name__ == "__main__":
	import mimetypes
	mime, encoding = mimetypes.guess_type('asdf.txt')
	print "Mimetype for asdf.txt is ", mime
	
	kdehelper = helper()
	icon = kdehelper.iconForMime(mime)
	print "Generic icon name for the mime is ", icon
	
	iconpath = kdehelper.iconPath(icon, 32)
	print "icon path is ", iconpath
